#include "global.h"
#include "write.h"
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <algorithm>

void get_start_end(int &st,int &ed,int tag)
{
	static int _st[MAX_TAG_NUM][MAX_TIME_SLICING],_ed[MAX_TAG_NUM][MAX_TIME_SLICING];
	if(_st[tag][timestamp])
	{
		st=_st[tag][timestamp],ed=_ed[tag][timestamp];
		return ;
	}
	const int step=900;
	long long ss=0,se=0,de=0;
	for(int i=step;i<=T+EXTRA_TIME;i+=step) if((sum[M][i]-sum[0][i])*3>=N*V*0.7)
	{
		ss+=sum[tag-(tag&1?1:2)][i];
		se+=sum[tag+(tag&1?1:0)][i];
		de+=sum[M][i];
	}
	st=int(ss*vdisk.V/de),ed=int(se*vdisk.V/de);
	ss=0,se=0,de=0;
	for(int i=0;i<12*1800;i+=step)
	{
		int time=min(i+timestamp,T+EXTRA_TIME);
		ss+=sum[tag-1][time]-sum[ tag-(tag&1?1:2) ][time];
		se+=sum[tag][time]-sum[ tag-(tag&1?1:2) ][time];
		de+=sum[ tag+(tag&1?1:0) ][time]-sum[ tag-(tag&1?1:2) ][time];
	}
	int dis=ed-st;
	_st[tag][timestamp]=st+(dis*ss/de)+1;
	_ed[tag][timestamp]=st+(dis*se/de);
	st=_st[tag][timestamp],ed=_ed[tag][timestamp];
	// if(st>V||ed>V||st<1||ed<1) fprintf(stderr,"%d %d %lld %lld %lld %d\n",st,ed,ss,se,de,tag);
}
int outrange[MAX_TAG_NUM];
void do_object_write(int object_id, int tag)
{
	int current_write_point = 0;

	int st,ed;
	get_start_end(st,ed,tag);
	// fprintf(stderr,"%d %d %d %d %d\n",st,ed,object_id,tag,vdisk.V);
	int stpoint=(tag&1)?st:ed;
	int side=(tag&1)?ed:st;
	int step=(tag&1)?1:-1;
	vdisk.linear_detector(object_id,stpoint,side,step);
}

struct write_pair {
	int id,size,tag;
}wt[MAX_OBJECT_NUM];

inline bool write_cmp(write_pair a,write_pair b) {
	return a.size==b.size?a.tag<b.tag:a.size>b.size;
}

void write_action2()
{
	int n_write;
    n_write = n_writes[timestamp];
	for (int i = 1; i <= n_write; i++) {
        const auto& write_tuple = write_datas[timestamp].at(i - 1);
        wt[i].id = get<0>(write_tuple);
        wt[i].size = get<1>(write_tuple);
        // tag = get<2>(write_tuple);
        wt[i].tag = vtag[object[wt[i].id].tag];
	}
	std::sort(wt+1,wt+n_write+1,write_cmp);

	for (int i = 1; i <= n_write; i++) {
		int id, size, tag;
		id=wt[i].id;size=wt[i].size;tag=wt[i].tag;

		object[id].last_request_point = 0;
		object[id].is_delete = false;
		
		for (int j = 1; j <= REP_NUM; j++)
			object[id].unit[j] = static_cast<int*>(malloc(sizeof(int) * (size + 1)));
		do_object_write(id, tagpos[tag]);

		if(Round !=2) putint(id);
		for (int j = 1; j <= REP_NUM; j++) {
			if(Round !=2) putint(object[id].replica[j],0);
			for (int k = 1; k <= size; k++) {
				if(Round !=2) putchar(' '),putint(object[id].unit[j][k],0);
			}
			if(Round !=2) putchar('\n');
		}
	}
	if(timestamp%1800==0)
	{
		for(int i=1;i<=M;i++) fprintf(stderr,"%d ",outrange[i]),outrange[i]=0;
		fprintf(stderr,"\n");
	}

	if(Round !=2) fflush(stdout);
}
